<?php
declare(strict_types=1);

namespace App\AdminApi\Module\User\Service;

use App\AdminApi\Module\System\Traits\ConfigureTraits;
use App\Common\Enums\SexEnums;
use App\Common\Enums\StatusEnums;
use App\Common\Model\User\UserModel;
use App\Sys;
use Hyperf\Database\Model\Collection;
use Zms\AdminElementPlus\FormCreate\Form;
use Zms\AdminElementPlus\FormCreate\FormItem;
use Zms\Basics\BasicsServe;
use Zms\Exception\AppException;
use Zms\Unit\Arr;
use Zms\Unit\Lists;
use Zms\Validate\Type;

/**
 * 用户
 * @method UserModel getModel()
 */
class UserService extends BasicsServe
{
    use ConfigureTraits;

    public static function model(): string
    {
        return UserModel::class;
    }


    /**
     * @describe 检测手机号是否占用
     * @user zlf <zms-pro@qq.com> 2025/3/11
     * @param string $mobile
     * @param int|null $id
     * @return bool
     */
    public function isPhoneOccupied(string $mobile, ?int $id = null): bool
    {
        $query = $this->search(['mobile' => $mobile]);
        if ($id) {
            $query->where('id', '!=', $id);
        }
        return $query->exists();
    }


    /**
     * 会员配置
     * @param $configure
     * @return array
     */
    public function getUserFormRule($configure): array
    {
        return [
            FormItem::Switchs('open_reg', '允许注册', (string)$configure['open_reg'] ?? '1')->activeText('允许注册')->required()->inactiveText('禁止注册')->hint('关闭后将禁止新用户注册'),
            FormItem::ImageInput('avatar', '默认头像', $configure['avatar'] ?? '')->required()
        ];
    }


    /**
     * 会员配置验证
     * @param $configure
     * @return array
     */
    public function getUserValidateRule(): array
    {
        return [
            'rule' => [
                ['open_reg', Type::REQUIRED],
                ['open_reg', Type::IN, 'enums' => [0, 1]],

                ['avatar', Type::REQUIRED],
                ['avatar', Type::STRING],
            ],
            'label' => [
                'open_reg' => '允许注册',
                'avatar' => '默认头像'
            ]
        ];
    }


    /**
     * @describe 设置会员信息
     * @user zlf <zms-pro@qq.com> 2025/3/11
     * @param array $data
     * @return ?UserModel
     * @throws AppException
     */
    public function saveUserData(array $data): ?UserModel
    {

        $id = $data['id'] ?? 0;
        unset($data['id']);

        /**
         * 获取用户模型
         * @var UserModel $user
         */
        $user = $id ? $this->search(['id' => $id])->first() : $this->getModel();
        if (!$user) {
            throw new AppException("编辑失败,会员信息已失效");
        }
        if (isset($data['mobile']) && $data['mobile']) {
            if ($this->isPhoneOccupied($data['mobile'], $user->id)) {
                throw new AppException('手机号已绑定其他账号');
            }
        }
        $user->setAttributes($data);

        return $user->save() ? $user : null;
    }

    /**
     * @describe 获取会员详情
     * @user zlf <zms-pro@qq.com> 2025/3/11
     * @param array|string $where
     * @return array
     * @throws AppException
     */
    public function getUserDetail(array|string $where): array
    {
        /**
         * @var UserModel $user
         */
        $user = $this->search($where)->first();
        if (!$user) {
            throw new AppException("会员已失效");
        }
        $result['user'] = [//基础资料
            "id" => $user->id,
            "avatar" => $user->avatar,
            "level_id" => $user->level_id,
            "_level" => Sys::container(LevelService::class)->getJoinValue($user->level_id),
            "mobile" => $user->mobile,
            "nickname" => $user->nickname,
            "sex" => $user->sex,
            "_sex" => SexEnums::Explain($user->sex),
            "status" => $user->status,
            "tags_ids" => $user->tags_ids,
            "_tags" => Sys::container(TagsService::class)->getJoinValue($user->tags_ids),
            "created_at" => date("y-m-d H:i:s", $user->created_at),
            "last_login" => $user->last_login ? date("y-m-d H:i:s", $user->last_login) : ''
        ];
        return $result;
    }


    /**
     * @describe 表单信息
     * @user zlf <zms-pro@qq.com> 2025/3/11
     * @param string $id
     * @param string $field
     * @return Form
     * @throws AppException
     */
    public function userForm(string $id = '', string $field = ''): Form
    {
        $values = [];
        if ($id) {
            /**
             * @var UserModel $tags
             */
            $tags = $this->search(['id' => $id])->first();
            if (!$tags) {
                throw new AppException('编辑失败,标签已失效');
            }
            $rule[] = FormItem::Hidden('id', $tags->id);
            $values = [
                'nickname' => $tags->nickname,
                'mobile' => $tags->mobile,
                'avatar' => $tags->avatar,
                'sex' => (string)$tags->sex,
                'level_id' => (string)$tags->level_id,
                'tags_ids' => Lists::toStringList($tags->tags_ids),
                'status' => (string)$tags->status
            ];
        }
        $rule[] = FormItem::Input('nickname', '会员名称')->clearable(true)->maxlength(20)->required('请输入用户名称');
        $rule[] = FormItem::Input('mobile', '手机号码')->clearable(true)->maxlength(11);
        $rule[] = FormItem::ImageInput('avatar', '会员头像')->required('请选择会员头头像');
        $rule[] = FormItem::Select('sex', '性别')->options(SexEnums::Datas());
        $rule[] = FormItem::Select('level_id', '会员等级')->options(Sys::container(LevelService::class)->dictionary())->required();
        $rule[] = FormItem::SelectMuliple('tags_ids', '会员标签')->options(Sys::container(TagsService::class)->dictionary());
        $rule[] = FormItem::Select('status', '会员状态')->options(StatusEnums::Datas());
        if ($field) {
            $rule[] = FormItem::Hidden('field', $field);
        }
        return Form::create(($id ? '编辑会员信息' : '添加用户信息'))
            ->setRules($rule, $field ? ['id', 'field', $field] : [])
            ->setValues($values)
            ->setOptionFormInline(true);
    }


    /**
     * @describe 删除会员
     * @user zlf <zms-pro@qq.com> 2025/3/11
     * @param int $id
     * @return bool
     * @throws AppException
     */
    public function deletedUser(int $id): bool
    {
        $user = $this->search(['id' => $id])->first();
        if ($user) {
            if ($user->delete()) {
                return true;
            }
            return false;
        } else {
            throw new AppException("会员已失效,删除失败");
        }
    }


    /**
     * @describe 恢复软删除会员
     * @user zlf <zms-pro@qq.com> 2025/3/11
     * @param int $id
     * @return bool
     * @throws AppException
     */
    public function recycleUser(int $id): bool
    {
        /**
         * @var UserModel $user
         */
        $user = $this->onlyTrashed()->where(['id' => $id])->first();
        if ($user) {
            if ($user->restore()) {
                return true;
            }
            return false;
        } else {
            throw new AppException("会员已失效,恢复失败");
        }
    }


    /**
     * 获取用户概览
     * @return array
     */
    public function getOverviewData(): array
    {
        return [
            ['title' => "会员人数", 'precision' => 0, 'suffix' => "人", 'value' => $this->count()],
            ['title' => "今日新增", 'precision' => 0, 'suffix' => "人", 'value' => $this->search()->whereBetween('created_at', [strtotime(date('Y-m-d 00:00:00')), strtotime(date('Y-m-d 23:59:59')),])->count()],
            ['title' => "回收站", 'precision' => 0, 'suffix' => "人", 'value' => $this->onlyTrashed()->count()],
            ['title' => "冻结会员", 'precision' => 0, 'suffix' => "人", 'value' => $this->search(['status' => StatusEnums::DISABLED])->count()],
        ];
    }


    /*
     * 会员注册图表
     */
    public function getRegisterChart(): array
    {
        $map = [];
        $this->search()->select(['created_at'])->orderByRaw('id ASC')->chunk(200, function (Collection $users) use (&$map) {
            foreach ($users->toArray() as $user) {
                $time = date("Y-m-d", $user['created_at']);
                $map[$time] = ($map[$time] ?? 0) + 1;
            }
        });
        return [
            'labels' => array_keys($map),
            'values' => array_values($map)
        ];
    }


    /**
     * 获取会员等级数量数据
     * @return array
     */
    public function getLevelChart(): array
    {
        $query = $this->search();

        //获取全部用户分组统计
        $data = $query->groupBy('level_id')->selectRaw("`level_id`,COUNT(`level_id`) as num")->get()->toArray();
        if (count($data) === 0) {
            return [];
        }
        $data_map = Arr::map($data, 'level_id', 'num');
        //获取总人数
        $total = (int)array_sum(array_values($data_map));

        //获取全部级别
        $levels = Sys::container(LevelService::class)->dictionary();

        $chart = [];
        foreach ($levels as $level) {
            if (isset($data_map[$level['value']])) {
                $total = $total - intval($data_map[$level['value']]);
                $chart[] = [
                    'value' => intval($data_map[$level['value']]),
                    'name' => $level['label']
                ];
            }
        }
        //已失效的归入其他
        if ($total > 0) {
            $chart[] = ['value' => $total, 'name' => '其他'];
        }
        return $chart;
    }
}